package com.hmall.search.listener;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.hmall.search.domain.po.ItemDoc;
import com.hmall.api.client.ItemClient;
import com.hmall.api.dto.ItemDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;

@RequiredArgsConstructor
@Component
@Slf4j
public class ItemListener {

    private final RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
            HttpHost.create("http://192.168.18.132:9200")
    ));
    private final ItemClient itemClient;

    public void common(Long id) throws IOException {
        ItemDTO itemDTO = itemClient.queryItemById(id);
        ItemDoc itemDoc = BeanUtil.copyProperties(itemDTO, ItemDoc.class);
        itemDoc.setUpdateTime(LocalDateTime.now());

        try {
            // 判断文档是否已存在，决定使用 update 还是 index
            GetRequest getRequest = new GetRequest("items", id.toString());
            boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);

            if (exists) {
                // 局部更新：使用 UpdateRequest
                UpdateRequest request = new UpdateRequest("items", id.toString());
                request.doc(JSONUtil.toJsonStr(itemDoc), XContentType.JSON);
                client.update(request, RequestOptions.DEFAULT);
            } else {
                // 新增：使用 IndexRequest
                IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
                request.source(JSONUtil.toJsonStr(itemDoc), XContentType.JSON);
                client.index(request, RequestOptions.DEFAULT);
            }
        } catch (IOException | ElasticsearchException e) {
            log.error("Elasticsearch 操作失败，ID: {}", id, e);
            throw e;
        }
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "search.item.index.queue", durable = "true"),
            exchange = @Exchange(value = "search.direct"),
            key = {"item.index"}
    ))
    private void listenItemIndex(Long id) throws IOException {
        log.info("监听到商品新增：{}", id);
        common(id);
        log.info("商品新增成功：{}", id);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "search.item.delete.queue", durable = "true"),
            exchange = @Exchange(value = "search.direct"),
            key = {"item.delete"}
    ))
    private void listenItemDelete(Long id) throws IOException {
        log.info("监听到商品删除：{}", id);
        DeleteRequest request = new DeleteRequest("items", id.toString());
        client.delete(request, RequestOptions.DEFAULT);
        log.info("商品删除成功：{}", id);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "search.item.update.queue", durable = "true"),
            exchange = @Exchange(value = "search.direct"),
            key = {"item.update"}
    ))
    private void listenItemUpdate(Long id) throws IOException {
        log.info("监听到商品修改：{}", id);
        common(id);
        log.info("商品修改成功：{}", id);
    }
}
